<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Example: Stack Support</title>
    <link rel="stylesheet" href="http://yui.yahooapis.com/3.4.0pr3/build/cssgrids/grids-min.css">
    <link rel="stylesheet" href="../assets/css/main.css">
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
    <script src="../../build/yui/yui-min.js"></script>
</head>
<body>

<div id="doc">
    <h1>Example: Stack Support</h1>

    

    <div class="yui3-g">
        <div id="main" class="yui3-u">
            <div class="content"><style type="text/css" scoped>
/* Hide overlay markup while loading, if js is enabled */
.yui3-js-enabled .yui3-overlay-loading {
    top:-1000em;
    left:-1000em;
    position:absolute;
}

/* Overlay Look/Feel */
.yui3-overlay-content {
    padding:3px;
    border:1px solid #000;
    background-color:#aaa;
}

.yui3-overlay-content .yui3-widget-hd {
    padding:5px;
    border:2px solid #aa0000;
    background-color:#fff;
}

.yui3-overlay-content .yui3-widget-bd {
    padding:5px;
    border:2px solid #0000aa;
    background-color:#fff;
}

.yui3-overlay-content .yui3-widget-ft {
    padding:5px;
    border:2px solid #00aa00;
    background-color:#fff;
}

/* Example Layout CSS */
.overlay-example {
    padding:5px;
    height:25em;
}

.overlay-example select {
    width:35em;
} 
</style>

<div class="intro">
    <p>This example shows how you can work with the <code>zIndex</code> attribute which the Overlay supports, to implement a simple <code>bringToTop</code> function. The example code also listens for changes in the <code>zIndex</code> attribute, which it uses to update the content of the overlay, when it is brought to the top of the stack.</p>    
</div>

<div class="example">
    <p><strong>Click on an Overlay to switch it's zIndex with the highest zIndex in the stack, bringing it to the top of the stack</strong></p>

<div class="overlay-example" id="overlay-stack">
    <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nunc pretium quam eu mi varius pulvinar. Duis orci arcu, ullamcorper sit amet, luctus ut, interdum ac, quam. Pellentesque euismod. Nam tincidunt, purus in ultrices congue, urna neque posuere arcu, aliquam tristique purus sapien id nulla. Etiam rhoncus nulla at leo. Cras scelerisque nisl in nibh. Sed eget odio. Morbi elit elit, porta a, convallis sit amet, rhoncus non, felis. Mauris nulla pede, pretium eleifend, porttitor at, rutrum id, orci. Quisque non urna. Nulla aliquam rhoncus est.</p>
    <p>
        <select class="needs-shim">
            <option>Prevent IE6 Bleedthrough</option>
        </select>
    </p>
    <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nunc pretium quam eu mi varius pulvinar. Duis orci arcu, ullamcorper sit amet, luctus ut, interdum ac, quam. Pellentesque euismod. Nam tincidunt, purus in ultrices congue, urna neque posuere arcu, aliquam tristique purus sapien id nulla. Etiam rhoncus nulla at leo. Cras scelerisque nisl in nibh. Sed eget odio. Morbi elit elit, porta a, convallis sit amet, rhoncus non, felis. Mauris nulla pede, pretium eleifend, porttitor at, rutrum id, orci. Quisque non urna. Nulla aliquam rhoncus est.</p>
</div>

<script type="text/javascript">
YUI().use("overlay", function(Y) {

    var overlays = [],
        overlay,
        n = 6,
        xy = Y.one("#overlay-stack").getXY();

    function getOverlayXY(xy, i) {
        return [xy[0] + i * 60, xy[1] + i * 40];
    }

    for (var i = 0; i < n; ++i) {

        ovrXY = getOverlayXY(xy, i);
        ovrZIndex = i+1;

        // Setup n Overlays, with increasing zIndex values
        overlay = new Y.Overlay({
            zIndex:ovrZIndex,
            xy:ovrXY,
            width:"8em",
            height:"8em",
            headerContent: 'Overlay <span class="yui3-ovr-number">' + i + '</span>',
            bodyContent: "zIndex = " + ovrZIndex
        });

        overlay.render("#overlay-stack");
        overlays.push(overlay);

        // Update body whenever zIndex changes
        overlay.after("zIndexChange", function(e) {
            this.set("bodyContent", "zIndex = " + e.newVal);
        });
    }

    function onStackMouseDown(e) {
        var widget = Y.Widget.getByNode(e.target);

        // If user clicked on an Overlay, bring it to the top of the stack
        if (widget && widget instanceof Y.Overlay) {
            bringToTop(widget);
        }
    }

    // zIndex comparator
    function byZIndexDesc(a, b) {
        if (!a || !b || !a.hasImpl(Y.WidgetStack) || !b.hasImpl(Y.WidgetStack)) {
            return 0;
        } else {
            var aZ = a.get("zIndex");
            var bZ = b.get("zIndex");

            if (aZ > bZ) {
                return -1;
            } else if (aZ < bZ) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    function bringToTop(overlay) {

        // Sort overlays by their numerical zIndex values
        overlays.sort(byZIndexDesc);

        // Get the highest one
        var highest = overlays[0];

        // If the overlay is not the highest one, switch zIndices
        if (highest !== overlay) {
            var highestZ = highest.get("zIndex");
            var overlayZ = overlay.get("zIndex");

            overlay.set("zIndex", highestZ);
            highest.set("zIndex", overlayZ);
        }
    }

    Y.on("mousedown", onStackMouseDown, "#overlay-stack");
});
</script>

</div>

<h2>Basic Overlay Stackability (zIndex and shim support)</h2>

<h3>Setting Up The YUI Instance</h3>

<p>As with the <a href="overlay-xy.html">"Basic XY Positioning"</a> example, to create an instance of an Overlay on your page, the only module you need to request is the <code>overlay</code> module. The <code>overlay</code> module will pull in the <code>widget</code>, <code>widget-stack</code>, <code>widget-position</code>, <code>widget-position-align</code>, <code>widget-position-constrain</code> and <code>widget-stdmod</code> extensions it uses.</p>

<pre class="code prettyprint">YUI({...}).use(&quot;overlay&quot;, function(Y) {
    &#x2F;&#x2F; We&#x27;ll write example code here, where we have a Y.Overlay class available.
});</pre>


<p>Using the <code>overlay</code> module will also pull down the default CSS required for overlay, on top of which we only need to add our required look/feel CSS for the example.</p>

<h3>Instantiating The Overlay</h3>

<p>For this example we'll instantiate Overlays from script, as we did for the <a href="overlay-align.html">"Alignment Support"</a> example. We'll create 6 Overlay instances and give them increasing zIndex and xy attribute values:</p>

<pre class="code prettyprint">function getOverlayXY(xy, i) {
    return [xy[0] + i * 60, xy[1] + i * 40];
}

for (var i = 0; i &lt; n; ++i) {

    ovrXY = getOverlayXY(xy, i);
    ovrZIndex = i+1;

    &#x2F;&#x2F; Setup n Overlays, with increasing zIndex values and xy positions
    overlay = new Y.Overlay({
        zIndex:ovrZIndex,
        xy:ovrXY,

        width:&quot;8em&quot;,
        height:&quot;8em&quot;,
        headerContent: &#x27;Overlay &lt;span class=&quot;yui3-ovr-number&quot;&gt;&#x27; + i + &#x27;&lt;&#x2F;span&gt;&#x27;,
        bodyContent: &quot;zIndex = &quot; + ovrZIndex
    });

    overlay.render(&quot;#overlay-stack&quot;);

    ...

}</pre>


<p>We store the Overlay instances in an <code>overlays</code> array, which we'll later use to sort the Overlays by their zIndex values. We also setup a listener for the <code>zIndex</code> attribute change event, which will update the body section of the Overlay to display its new zIndex value.</p>

<pre class="code prettyprint">overlays.push(overlay);

&#x2F;&#x2F; Update body whenever zIndex changes
overlay.after(&quot;zIndexChange&quot;, function(e) {
    this.set(&quot;bodyContent&quot;, &quot;zIndex = &quot; + e.newVal);
});</pre>


<h3>Handling MouseDown Using Widget.getByNode</h3>

<p>The <code>Widget</code> class has a static <code>getByNode</code> method which can be used to retrieve Widget instances based on a node reference. The method will return the closest Widget which contains the given node.</p>

<p>
We'll use this method in a click listener bound to the container of the example ("#overlay-stack"). Target nodes of click events bubbled up to this example container, will be passed to the <code>Widget.getByNode</code> method, to see if an Overlay was clicked on.
</p>

<pre class="code prettyprint">function onStackMouseDown(e) {
    var widget = Y.Widget.getByNode(e.target);

    &#x2F;&#x2F; If user clicked on an Overlay, bring it to the top of the stack
    if (widget &amp;&amp; widget instanceof Y.Overlay) {
        bringToTop(widget);
    }
}

Y.on(&quot;mousedown&quot;, onStackMouseDown, &quot;#overlay-stack&quot;);</pre>


<p>If an Overlay was clicked on, we invoke the simple bringToTop method which will set the zIndex of the clicked Overlay to the highest current Overlay zIndex value.</p>

<h3>The <code>bringToTop</code> Implementation</h3>

<p>We use a basic comparator function to sort the array of Overlays we have. The comparator makes sure the array element we're dealing with <a href="../widget/widget-build.html">has a <code>WidgetStack</code> implementation</a> (which Overlays do) and if so, sorts them in descending <code>zIndex</code> attribute value order:</p>

<pre class="code prettyprint">&#x2F;&#x2F; zIndex comparator
function byZIndexDesc(a, b) {
    if (!a || !b || !a.hasImpl(Y.WidgetStack) || !b.hasImpl(Y.WidgetStack)) {
        return 0;
    } else {
        var aZ = a.get(&quot;zIndex&quot;);
        var bZ = b.get(&quot;zIndex&quot;);

        if (aZ &gt; bZ) {
            return -1;
        } else if (aZ &lt; bZ) {
            return 1;
        } else {
            return 0;
        }
    }
}</pre>


<p>Once sorted, for the purposes of the example, we simply switch the <code>zIndex</code> of the "highest" Overlay, with the Overlay which was clicked on, giving the selected Overlay the highest zIndex value:</p>

<pre class="code prettyprint">function bringToTop(overlay) {

    &#x2F;&#x2F; Sort overlays by their numerical zIndex values
    overlays.sort(byZIndexDesc);

    &#x2F;&#x2F; Get the highest one
    var highest = overlays[0];

    &#x2F;&#x2F; If the overlay is not the highest one, switch zIndices
    if (highest !== overlay) {
        var highestZ = highest.get(&quot;zIndex&quot;);
        var overlayZ = overlay.get(&quot;zIndex&quot;);

        overlay.set(&quot;zIndex&quot;, highestZ);
        highest.set(&quot;zIndex&quot;, overlayZ);
    }
}</pre>


<h3>CSS: Overlay Look/Feel</h3>

<p>As mentioned in the <a href="overlay-xy.html">"Basic XY Positioning"</a> example, the overlay.css Sam Skin file (build/overlay/assets/skins/sam/overlay.css) provides the default functional CSS for the overlay. Namely the CSS rules to hide the overlay, and position it absolutely. However there's no default out-of-the-box look/feel applied to the Overlay widget.</p>

<p>The example provides it's own look and feel for the Overlay, by defining rules for the content box, header and body sections:</p>

<pre class="code prettyprint">&#x2F;* Overlay Look&#x2F;Feel *&#x2F;
.yui3-overlay-content {
    padding:2px;
    border:1px solid #000;
    background-color:#aaa;
    font-size:93%;
}

.yui3-overlay-content .yui3-widget-hd {
    font-weight:bold;
    text-align:center;
    padding:2px;
    border:2px solid #aa0000;
    background-color:#fff;
}

.yui3-overlay-content .yui3-widget-bd {
    text-align:left;
    padding:2px;
    border:2px solid #0000aa;
    background-color:#fff;
}

.yui3-overlay-content .yui3-widget-hd .yui3-ovr-number {
    color:#aa0000;
}</pre>


<h2>Complete Example Source</h2>
<pre class="code prettyprint">&lt;p&gt;&lt;strong&gt;Click on an Overlay to switch it&#x27;s zIndex with the highest zIndex in the stack, bringing it to the top of the stack&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;

&lt;div class=&quot;overlay-example&quot; id=&quot;overlay-stack&quot;&gt;
    &lt;p&gt;Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nunc pretium quam eu mi varius pulvinar. Duis orci arcu, ullamcorper sit amet, luctus ut, interdum ac, quam. Pellentesque euismod. Nam tincidunt, purus in ultrices congue, urna neque posuere arcu, aliquam tristique purus sapien id nulla. Etiam rhoncus nulla at leo. Cras scelerisque nisl in nibh. Sed eget odio. Morbi elit elit, porta a, convallis sit amet, rhoncus non, felis. Mauris nulla pede, pretium eleifend, porttitor at, rutrum id, orci. Quisque non urna. Nulla aliquam rhoncus est.&lt;&#x2F;p&gt;
    &lt;p&gt;
        &lt;select class=&quot;needs-shim&quot;&gt;
            &lt;option&gt;Prevent IE6 Bleedthrough&lt;&#x2F;option&gt;
        &lt;&#x2F;select&gt;
    &lt;&#x2F;p&gt;
    &lt;p&gt;Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nunc pretium quam eu mi varius pulvinar. Duis orci arcu, ullamcorper sit amet, luctus ut, interdum ac, quam. Pellentesque euismod. Nam tincidunt, purus in ultrices congue, urna neque posuere arcu, aliquam tristique purus sapien id nulla. Etiam rhoncus nulla at leo. Cras scelerisque nisl in nibh. Sed eget odio. Morbi elit elit, porta a, convallis sit amet, rhoncus non, felis. Mauris nulla pede, pretium eleifend, porttitor at, rutrum id, orci. Quisque non urna. Nulla aliquam rhoncus est.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;

&lt;script type=&quot;text&#x2F;javascript&quot;&gt;
YUI().use(&quot;overlay&quot;, function(Y) {

    var overlays = [],
        overlay,
        n = 6,
        xy = Y.one(&quot;#overlay-stack&quot;).getXY();

    function getOverlayXY(xy, i) {
        return [xy[0] + i * 60, xy[1] + i * 40];
    }

    for (var i = 0; i &lt; n; ++i) {

        ovrXY = getOverlayXY(xy, i);
        ovrZIndex = i+1;

        &#x2F;&#x2F; Setup n Overlays, with increasing zIndex values
        overlay = new Y.Overlay({
            zIndex:ovrZIndex,
            xy:ovrXY,
            width:&quot;8em&quot;,
            height:&quot;8em&quot;,
            headerContent: &#x27;Overlay &lt;span class=&quot;yui3-ovr-number&quot;&gt;&#x27; + i + &#x27;&lt;&#x2F;span&gt;&#x27;,
            bodyContent: &quot;zIndex = &quot; + ovrZIndex
        });

        overlay.render(&quot;#overlay-stack&quot;);
        overlays.push(overlay);

        &#x2F;&#x2F; Update body whenever zIndex changes
        overlay.after(&quot;zIndexChange&quot;, function(e) {
            this.set(&quot;bodyContent&quot;, &quot;zIndex = &quot; + e.newVal);
        });
    }

    function onStackMouseDown(e) {
        var widget = Y.Widget.getByNode(e.target);

        &#x2F;&#x2F; If user clicked on an Overlay, bring it to the top of the stack
        if (widget &amp;&amp; widget instanceof Y.Overlay) {
            bringToTop(widget);
        }
    }

    &#x2F;&#x2F; zIndex comparator
    function byZIndexDesc(a, b) {
        if (!a || !b || !a.hasImpl(Y.WidgetStack) || !b.hasImpl(Y.WidgetStack)) {
            return 0;
        } else {
            var aZ = a.get(&quot;zIndex&quot;);
            var bZ = b.get(&quot;zIndex&quot;);

            if (aZ &gt; bZ) {
                return -1;
            } else if (aZ &lt; bZ) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    function bringToTop(overlay) {

        &#x2F;&#x2F; Sort overlays by their numerical zIndex values
        overlays.sort(byZIndexDesc);

        &#x2F;&#x2F; Get the highest one
        var highest = overlays[0];

        &#x2F;&#x2F; If the overlay is not the highest one, switch zIndices
        if (highest !== overlay) {
            var highestZ = highest.get(&quot;zIndex&quot;);
            var overlayZ = overlay.get(&quot;zIndex&quot;);

            overlay.set(&quot;zIndex&quot;, highestZ);
            highest.set(&quot;zIndex&quot;, overlayZ);
        }
    }

    Y.on(&quot;mousedown&quot;, onStackMouseDown, &quot;#overlay-stack&quot;);
});
&lt;&#x2F;script&gt;</pre>

</div>
        </div>

        <div id="sidebar" class="yui3-u">
            

            
                <div class="sidebox">
                    <div class="hd">
                        <h2 class="no-toc">Examples</h2>
                    </div>

                    <div class="bd">
                        <ul class="examples">
                            
                                
                                    <li data-description="Shows how to instantiate a basic Overlay instance, and use the Overlay&#x27;s basic XY positioning support.">
                                        <a href="overlay-xy.html">Basic XY Positioning</a>
                                    </li>
                                
                            
                                
                                    <li data-description="Shows how to use the Overlay&#x27;s XY alignment support, to align the Overlay relative to another element, or to the viewport.">
                                        <a href="overlay-align.html">Alignment Support</a>
                                    </li>
                                
                            
                                
                                    <li data-description="Shows how to use the Overlay&#x27;s zindex and shim support when positioning Overlays above other elements on the page.">
                                        <a href="overlay-stack.html">Stack Support</a>
                                    </li>
                                
                            
                                
                                    <li data-description="Shows how to modify content in the Overlay&#x27;s header, body and footer sections.">
                                        <a href="overlay-stdmod.html">Standard Module Support</a>
                                    </li>
                                
                            
                                
                                    <li data-description="Shows how to use Overlay&#x27;s constrainment support, to limit the XY value which can be set for an Overlay.">
                                        <a href="overlay-constrain.html">Constrain Support</a>
                                    </li>
                                
                            
                                
                                    <li data-description="Shows how to create a simple plugin to retrieve content for the Overlay using the io utility.">
                                        <a href="overlay-io-plugin.html">IO Plugin</a>
                                    </li>
                                
                            
                                
                                    <li data-description="Shows how to create a simple plugin to animate the Overlay&#x27;s movement and visibility.">
                                        <a href="overlay-anim-plugin.html">Animation Plugin</a>
                                    </li>
                                
                            
                                
                            
                                
                            
                        </ul>
                    </div>
                </div>
            

            
                <div class="sidebox">
                    <div class="hd">
                        <h2 class="no-toc">Examples That Use This Component</h2>
                    </div>

                    <div class="bd">
                        <ul class="examples">
                            
                                
                            
                                
                            
                                
                            
                                
                            
                                
                            
                                
                            
                                
                            
                                
                                    <li data-description="Creating an accessible menu button using the Focus Manager Node Plugin, Event&#x27;s delegation support and mouseenter event, along with the Overlay widget and Node&#x27;s support for the WAI-ARIA Roles and States.">
                                        <a href="../node-focusmanager/node-focusmanager-3.html">Accessible Menu Button</a>
                                    </li>
                                
                            
                                
                                    <li data-description="Use StyleSheet to adjust the CSS rules applying a page theme from user input">
                                        <a href="../stylesheet/stylesheet-theme.html">Adjusting a Page Theme on the Fly</a>
                                    </li>
                                
                            
                        </ul>
                    </div>
                </div>
            
        </div>
    </div>
</div>

<script src="../assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>

</body>
</html>
